package com.lkl.demo.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lkl.demo.common.exception.BusinessException;
import com.lkl.demo.common.result.R;
import com.lkl.demo.common.result.ResponseEnum;
import com.lkl.demo.constant.Constants;
import com.lkl.demo.entity.User;
import com.lkl.demo.vo.LoginVo;
import com.lkl.demo.mapper.UserMapper;
import com.lkl.demo.service.IUserService;
import com.lkl.demo.utils.CookieUtil;
import com.lkl.demo.utils.MD5Util;
import com.lkl.demo.utils.ServletUtils;
import com.lkl.demo.utils.UUIDUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;

import static com.lkl.demo.constant.Constants.LOGIN_THRESHOLD;

/**
 * 用户表
 *
 * @author likelong
 * @date 2022-07-25
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public R doLogin(LoginVo loginVo) {
        String mobile = loginVo.getMobile();
        String password = loginVo.getPassword();

        //获取密码输出错误次数
        Integer thresholdR = (Integer) redisTemplate.opsForValue().get(LOGIN_THRESHOLD + mobile);
        if (thresholdR != null) {
            if (thresholdR >= Constants.PASSWORD_ERROR_THRESHOLD) {
                throw new BusinessException("密码输入错误" + thresholdR + "次，请" + Constants.CONTINUE_LOGIN_MINUTES + "分钟后再试!");
            }
        }

//        if (StringUtils.isEmpty(mobile) || StringUtils.isEmpty(password)) {
//            return R.setResult(ResponseEnum.LOGINVO_NULL_ERROR);
//        }
//        if (!ValidatorUtil.isMobile(mobile)) {
//            return R.setResult(ResponseEnum.MOBILE_ERROR);
//        }

        User user = baseMapper.selectById(mobile);
        if (user == null) {
            throw new BusinessException(ResponseEnum.LOGIN_ERROR);
        }

//        if (!MD5Util.formPassToDBPass(password, user.getSalt()).equals(user.getPassword())) {
//            throw new BusinessException(ResponseEnum.LOGIN_ERROR);
//        }

        // 应该是前端加密一次后端加密一次，但是前端md5.js有问题，前端就不加密了
        if (!MD5Util.inputPassToDBPass(password, user.getSalt()).equals(user.getPassword())) {
            // 密码错误
            updateThreshold(mobile);
            throw new BusinessException(ResponseEnum.LOGIN_ERROR);
        }

        String token = (String) redisTemplate.opsForValue().get(Constants.ACCESS_USERID + user.getId());

        if (!StringUtils.isEmpty(token)) {
            redisTemplate.delete(Constants.ACCESS_TOKEN + token);
        }
        createToken(user);
        return R.ok();
    }

    public void createToken(User user) {
        // 生成token
        String token = UUIDUtil.uuid();
        redisTemplate.opsForValue().set(Constants.ACCESS_USERID + user.getId(), token, Constants.EXPIRE, TimeUnit.SECONDS);
        //将用户信息存入redis
        redisTemplate.opsForValue().set(Constants.ACCESS_TOKEN + token, user, Constants.EXPIRE, TimeUnit.SECONDS);
        CookieUtil.setCookie(ServletUtils.getRequest(), ServletUtils.getResponse(), "token", token);
    }

    /**
     * 登录错误次数阀值记录
     *
     * @param mobile 用户手机号
     */
    private void updateThreshold(String mobile) {
        Integer thresholdR = (Integer) redisTemplate.opsForValue().get(LOGIN_THRESHOLD + mobile);
        if (thresholdR != null) {
            redisTemplate.opsForValue().set(LOGIN_THRESHOLD + mobile, thresholdR + 1, Constants.CONTINUE_LOGIN_MINUTES, TimeUnit.MINUTES);
        } else {
            redisTemplate.opsForValue().set(LOGIN_THRESHOLD + mobile, 1, Constants.CONTINUE_LOGIN_MINUTES, TimeUnit.MINUTES);
        }

    }
}
